#============================================================================
#
#　** Wall Tile Extension　* Ver1.00　
# * Creator: 月紳士 (Moon Man)     ( http://tsukishinshi.blog73.fc2.com )
# 
#　* RPG Maker VX RGSS2 Script
#
# * Translation by: Mr. Anonymous ( http://anonymouscreations.we.bs )
#
#============================================================================
=begin

This script chiefly enhances the movement judgment and enables the following 
expressions for the wall tiles. 

.Basic Features
　　The following functions work by using this script:

　* Enables movement behind walls and atop roofs.

　*　Reproduction of the XP ceiling conceal, which makes designated tiles conceal 
  characters like they did in XP. 
  
 * Creates "invisible passage" so you can make secret passages or movement under 
  fake bridges.
 
　*　Added passability options.

　*　A function to create ladders/stairs which penetrate normally impassible tiles.

　* Bridges automatically act as such, having you walk on and under them, at the 
  same time if events do it, with no events to control it.

#------------------------------------------------------------------------------

* Tags

　* Bridge Passage Area
    When you need to create a bridge in which the player can move under when in
    a vehicle, first create a new area that contains said bridge, and name the
    area:
            <bridge>

　* Event Behind Roof/Ceiling/Wall/Cliff
    When you need to create an event that rests behind a roof, cieling, wall,
    cliff, etc, (if BACK_SEEING = true, when the player is 1 tile away from this
    event it will also be shown as semi-transparent) create an event and include 
    the follow tag in its name:

　　          <behind>

　* Event Behind Roof/Ceiling/Wall/Cliff (when BACK_SEEING = true)
    When you need to create an event that rests behind a roof, cieling, wall,
    cliff, etc, and is NOT shown as semi-transparent while near it, create an 
    event and include the follow tag in its name:

　　          <hidebehind>

=end

#==============================================================================
# * Customization
#==============================================================================

module Expansion_Passable
  # * Cliff Type Maps
  # In the following array, you may define what maps determined as "Cliff" maps.
  # These allow for recognition of certain tiles to function differently. This
  # is used to create a slope-like effect (different grass tile elevations) 
  # for some tiles without making it global across all maps. It's best to test
  # this function out for yourself by testing it in the demo, then remove the
  # 5 (by default) from the array and try it again.
  # Note that since this is an array, it can contain multiple map IDs as such:
  # CLIFF_MAP = [5, 6, 7, 12, 30]
  CLIFF_MAP = [1]
  
  # * True wall depth
  # This allows you to specify whether the player can move down the full depth 
  # of the wall or only the first tile. For example, if set as true, and a wall
  # is 3 tiles high + 1 tile for ceiling/roofing, then the player will be able
  # to move all the way down to the base of the wall (down three tiles).
  # It's easier just to test it both ways to understand.
  # true  : Wall depth and player moveability range is increased to wall scale.
  # false : Wall depth and player moveability is fixed at 1 tile.
  BACK_TILE_DEEP = false
  
  # * Display of character behind cieling tiles
  # This allows you to adjust whether the character is visible (semi-transparent)
  # or not displayed at all when the character is behind a roof/ceiling tile.
  # true  : Characters are draw semi-transparent
  # false : Characters are hidden
  BACK_SEEING = true
  
  # * Remove Shadow Tiles ID
  # The "No Shadow" tile indicates a tile that removes and autoshadow tile that
  # would normally be displayed on it. It is used for removing any awkward look
  # that would normally  be produced by creating special hills or cliffs.
  # When not using this feature, set the value as nil.
  SHADOW_ERASER_TILE_ID = 768
  
  # * Prohibit Docking Tile ID
  # The "No Docking" tile indicates a tile that does not allow for a vehicle to 
  # 'dock' at. It is used to determine features such as cliffs that the player
  # should not be allowed to dock on, given it would have raised elevation.
  # When not using this feature, set the value as nil.
  PROHIBITED_GET_OFF_TILE_ID = 769

  # * Walk Through Wall Tile ID
  # The "Walk Through" tile indicates a tile that allows the player to walk
  # through it, used specifically for segements where you allow the player to
  # walk through a given wall. 
  # When not using this feature, set the value as nil.
  ADDITION_BACK_TILE_ID = 770

  # * Delete Background Tile ID
  # The "No Background" tile indicates a tile that deletes the tile behind it.
  # It is primarily used for determining roof/cieling tiles with the player 
  # cannot walk behind.
  # When not using this feature, set the value as nil.
  DELETE_BACK_TILE_ID = 771
  REMOVE_TILE_MARKER = 783
  
end

#==============================================================================
# * Tile customization options (very advanced users only!)
#==============================================================================

module Data_Tile
  # Ceiling, roof, & terrain tile feature setup
  FUNCTION_TILE = [
   2816, 2960,                                     # Plains (field and outdoor)
   3200, 3344,                                     # Dry    (field and outdoor)
   3584, 3728,                                     # Desert (field and outdoor) 
   3968, 4016,                                     # Snow   (field and outdoor)
   4352, 4400, 4448, 4496, 4544, 4592, 4640, 4688, # Roof         (1st Column) 
   4736, 4784, 4832, 4880, 4928, 4976, 5024, 5072, # Wall         (1st Column)               
   5120, 5168, 5216, 5264, 5312, 5360, 5408, 5456, # Roof         (2nd Column) 
   5504, 5552, 5600, 5648, 5696, 5744, 5792, 5840, # Wall         (2nd Column)     
   5888, 5936, 5984, 6032, 6080, 6128, 6176, 6224, # Cave Ceiling (1st Column) 
   6272, 6320, 6368, 6416, 6464, 6512, 6560, 6608, # Cave Wall    (1st Column) 
   6656, 6704, 6752, 6800, 6848, 6896, 6944, 6992, # Cave Ceiling (2nd Column)
   7040, 7088, 7136, 7184, 7232, 7280, 7328, 7376, # Cave Wall    (2nd Column)
   7424, 7472, 7520, 7568, 7616, 7664, 7712, 7760, # Cave Ceiling (3rd Column) 
   7808, 7856, 7904, 7952, 8000, 8048, 8096, 8144, # Cave Wall    (3rd Column) 
   1952, 2000]                                     # Dummy TileIDs                   
   
  # * Horizontal bridge TileIDs 
  BRIDRE_LENGTH = [17, 18]

  # * Vertical bridge TileIDs 
  BRIDGE_BREADTH = [16, 19]
  
  # * TileIDs treated as entrances for stairs, ladders, and caves
  # When the player is on one of these tiles, the passage settings are altered
  # so that the player is constrainted within the tile's ideal passage.
  STEP = [67, 68, 69, 70, 71, 172, 173, 174, 175,
          260, 261, 262, 263, 268, 269, 270,
          271, 278, 279, 284, 285, 286, 287, 
          612, 613, 616, 617, 618, 619, 904,
          676, 668]      
  
  
  # * TileID for passability determination under bridges
  # The default of TileID 1664 is not visible within the editor and has no in-
  # game image. If not necessary, please do not change this value.
  UNDER_BRIDGE = 1664
  
end

#==============================================================================
# * Please do not change autotile setup 
#==============================================================================

module Data_Auto_Tile
  # Array for each direction in which the tiles have an edge (AutotileID)
  # Floor type
  VERGE_DOWN_A  = [28, 29, 30, 31, 33, 38, 39, 40, 41, 43, 44, 45, 46]
  VERGE_LEFT_A  = [16, 17, 18, 19, 32, 34, 35, 40, 41, 42, 43, 44, 46]
  VERGE_RIGHT_A = [24, 25, 26, 27, 32, 36, 37, 38, 39, 42, 44, 45, 46]
  VERGE_UP_A    = [20, 21, 22, 23, 33, 34, 35, 36, 37, 42, 43, 45, 46]
  
  # Wall Type
  VERGE_DOWN_B  = [ 8,  9, 10, 11, 12, 13, 14, 15]
  VERGE_LEFT_B  = [ 1,  3,  5,  7,  9, 11, 13, 15]
  VERGE_RIGHT_B = [ 4,  5,  6,  7, 12, 13, 14, 15]
  VERGE_UP_B    = [ 2,  3,  6,  7, 10, 11, 14, 15]

end

#==============================================================================
# ■ RPG::Area
#==============================================================================

class RPG::Area
  #--------------------------------------------------------------------------
  # ○ 公開インスタンス変数
  #--------------------------------------------------------------------------
  attr_accessor :ship_pass
end 

#==============================================================================
# ■ Game_Map
#------------------------------------------------------------------------------
# 　マップを扱うクラスです。スクロールや通行可能判定などの機能を持っています。
# このクラスのインスタンスは $game_map で参照されます。
#==============================================================================

class Game_Map
  #--------------------------------------------------------------------------
  # ○ 公開インスタンス変数
  #--------------------------------------------------------------------------
  attr_reader   :under_bridge_passages
  attr_reader   :back_tiles_position
  attr_reader   :keep_back_position
  attr_reader   :ex_data
  attr_reader   :prohibited_get_off
  #--------------------------------------------------------------------------
  # ◎ セットアップ
  #     map_id : マップ ID
  #--------------------------------------------------------------------------
  alias tig_ep_setup setup
  def setup(map_id)
    tig_ep_setup(map_id)
    @ex_data = Table.new(width, height, 3)
    @under_bridge_passages = {}
    @back_tiles_position = []
    @keep_back_position = []
    prohibited_get_off_setup
    setup_back_tiles
    shadow_eraser_tile_setup
  end
  #--------------------------------------------------------------------------
  # ○ 接岸禁止タイルのセットアップ
  #     map_id : マップ ID
  #--------------------------------------------------------------------------
  def prohibited_get_off_setup
    @prohibited_get_off = []
    return if Expansion_Passable::PROHIBITED_GET_OFF_TILE_ID == nil
    for x in 0...width
      for y in 0...height
        if @map.data[x, y, 2] == Expansion_Passable::PROHIBITED_GET_OFF_TILE_ID
          @map.data[x, y, 2] = 0
          @prohibited_get_off.push([x, y])
        end
      end
    end
  end
  #--------------------------------------------------------------------------
  # ○ 影消しタイルのセットアップ
  #--------------------------------------------------------------------------
  def shadow_eraser_tile_setup
    return if Expansion_Passable::SHADOW_ERASER_TILE_ID == nil
    for x in 0...width
      for y in 0...height
        if @map.data[x, y, 2] == Expansion_Passable::SHADOW_ERASER_TILE_ID
          r_x = round_x(x - 1)
          tile_id = @map.data[r_x, y, 0]

          if (4352...5888).include?(tile_id) or
             (6272...6656).include?(tile_id) or
             (7040...7424).include?(tile_id) or
             (7808...8192).include?(tile_id)
            dummy_tile_id = 2000 + auto_(tile_id)
          else
            dummy_tile_id = 1952 + auto_(tile_id)
          end
          
          @map.data[x, y, 2] = 0
          @map.data[r_x, y, 1] = @map.data[r_x, y, 0]
          @map.data[r_x, y, 0] = dummy_tile_id
        end
      end
    end
  end
  #--------------------------------------------------------------------------
  # ○ 指定座標のタイルIDの取得
  #--------------------------------------------------------------------------
  def point_tile_id(x, y)
    return [data[x, y, 0], data[x, y, 1], data[x, y, 2]]
  end
  #--------------------------------------------------------------------------
  # ○ オートタイルIDの取得（オートタイル郡の中で順番にIDをつけた独自のIDです）
  #--------------------------------------------------------------------------
  def auto_(tile_id)
    return 0 unless (1952...8192).include?(tile_id)
    return (tile_id - 1952) % 48
  end
  #--------------------------------------------------------------------------
  # ○ トップタイルIDの取得（オートタイル郡の最初のID）
  #--------------------------------------------------------------------------
  def top_(tile_id)
    return 0 if tile_id == nil
    return (tile_id - auto_(tile_id))
  end
  #--------------------------------------------------------------------------
  # ○ スクリプト機能を使用する屋根・天井・壁タイルか？
  #--------------------------------------------------------------------------
  def ceiling?(tile_id)
    return false unless Data_Tile::FUNCTION_TILE.include?(top_(tile_id))
    return true if wall?(tile_id)
    return true if (1952...2048).include?(tile_id)
    return true if (4352...4736).include?(tile_id)
    return true if (5120...5504).include?(tile_id)
    return true if (5888...6272).include?(tile_id)
    return true if (6656...7040).include?(tile_id)
    return (7424...7808).include?(tile_id)
  end
  #--------------------------------------------------------------------------
  # ○ スクリプト機能を使用する壁タイルか？
  #--------------------------------------------------------------------------
  def wall?(tile_id)
    return false unless Data_Tile::FUNCTION_TILE.include?(top_(tile_id))
    return true if (4736...5120).include?(tile_id)
    return true if (5504...5888).include?(tile_id)
    return true if (6272...6656).include?(tile_id)
    return true if (7040...7424).include?(tile_id)
    return (7808...8192).include?(tile_id)
  end
  #--------------------------------------------------------------------------
  # ○ スクリプト機能を使用する地形タイルか？
  #--------------------------------------------------------------------------
  def cliff?(tile_id)
    return false unless Data_Tile::FUNCTION_TILE.include?(top_(tile_id))
    return [2816, 3200, 3584, 2960, 3344, 3728, 4112].include?(top_(tile_id))
  end
  #--------------------------------------------------------------------------
  # ○ 指定の向きにオートタイルチップの境目があるか？
  #--------------------------------------------------------------------------
  def verge?(tile_id, direction)
    auto_tile_id = auto_(tile_id)
    
    return false if auto_tile_id == 0
    return false unless ceiling?(tile_id) or cliff?(tile_id)
    if (2000...2048).include?(tile_id) or
       (4352...5888).include?(tile_id) or
       (6272...6656).include?(tile_id) or
       (7040...7424).include?(tile_id) or
       (7808...8192).include?(tile_id)           # オートタイルの線画タイプ判別
      case direction # 壁タイプの場合　方向ごとに振り分け
      when 2 ; return true if Data_Auto_Tile::VERGE_DOWN_B.include?(auto_tile_id)
      when 4 ; return true if Data_Auto_Tile::VERGE_LEFT_B.include?(auto_tile_id) 
      when 6 ; return true if Data_Auto_Tile::VERGE_RIGHT_B.include?(auto_tile_id) 
      when 8 ; return true if Data_Auto_Tile::VERGE_UP_B.include?(auto_tile_id) 
      end
    else
      case direction # 床タイプの場合　方向ごとに振り分け
      when 2 ; return true if Data_Auto_Tile::VERGE_DOWN_A.include?(auto_tile_id) 
      when 4 ; return true if Data_Auto_Tile::VERGE_LEFT_A.include?(auto_tile_id) 
      when 6 ; return true if Data_Auto_Tile::VERGE_RIGHT_A.include?(auto_tile_id) 
      when 8 ; return true if Data_Auto_Tile::VERGE_UP_A.include?(auto_tile_id)
      end
    end
  end
  #--------------------------------------------------------------------------
  # ○ 指定の向きに通行不可の境目があるか？
  #--------------------------------------------------------------------------
  def rip?(tile_id, front_tile_id, direction)
    if Data_Tile::BRIDRE_LENGTH.include?(tile_id[2])
      return true if direction == 4 or direction == 6
    elsif Data_Tile::BRIDGE_BREADTH.include?(tile_id[2])
      return true if direction == 2 or direction == 8
    end
    if cliff?(tile_id[0])
      return false unless ceiling?(front_tile_id[0]) or cliff?(front_tile_id[0])
      if cliff?(front_tile_id[0]) and verge?(front_tile_id[0], 10 - direction)
        return false
      end
    end
    
    return verge?(tile_id[0], direction)
  end
  #--------------------------------------------------------------------------
  # ○ 指定の向きに準じた橋タイルか？（渡ることの出来る向きか）
  #--------------------------------------------------------------------------
  def bridge?(tile_id, direction)
    if direction == 2 or direction == 8
      return true if Data_Tile::BRIDRE_LENGTH.include?(tile_id)
    elsif direction == 4 or direction == 6
      return true if Data_Tile::BRIDGE_BREADTH.include?(tile_id)
    end
    return false
  end
  #--------------------------------------------------------------------------
  # ○ <船の橋下通過>処理をするエリアか？
  #--------------------------------------------------------------------------
  def ship_pass_area?(x, y)
    result = false
    for area in $data_areas.values
      next if area == nil
      next unless area.ship_pass
      next if $game_map.map_id != area.map_id
      next if x < area.rect.x
      next if y < area.rect.y
      next if x >= area.rect.x + area.rect.width
      next if y >= area.rect.y + area.rect.height
      result = true
    end
    return result
  end
  #--------------------------------------------------------------------------
  # ○ 裏回り用タイル存在座標ピックアップと通行判定初期化
  #--------------------------------------------------------------------------
  def setup_back_tiles
    
    for i in 4352...8192
      @passages[i] = 0x00 if ceiling?(i)         # 天井タイルの通行判定を○に
    end

    back_tiles = []                              # 裏回りタイル郡の生成
    for i in 2816...8192
      next unless ceiling?(i) or cliff?(i)
      next if wall?(i)
      next unless verge?(i, 8)
      if cliff?(i)
        next unless Expansion_Passable::CLIFF_MAP.include?(@map_id)
      end
      back_tiles.push(i)
    end

    for i in (Data_Tile::BRIDRE_LENGTH + Data_Tile::BRIDGE_BREADTH)
      @passages[i] = 0x10                       # 橋タイル通行判定を☆に
    end    
    @passages[Data_Tile::UNDER_BRIDGE] = 0x00    # 橋下用タイルの通行判定を○に
    
    for x in 0...width
      for reverse_y in 1..height
        y = height - reverse_y
        tile_id = point_tile_id(x, y)
         if (Data_Tile::BRIDRE_LENGTH + Data_Tile::BRIDGE_BREADTH).include?(tile_id[2])
          @back_tiles_position.push([x, y])
          if (2048...2815).include?(tile_id[0])
            @map.data[x, y, 1] = Data_Tile::UNDER_BRIDGE
            if ship_pass_area?(x, y)
              @under_bridge_passages[[x, y]] = 1
            else
              @under_bridge_passages[[x, y]] = 0
            end
          elsif @passages[tile_id[0]] != 0x06
            @map.data[x, y, 1] = Data_Tile::UNDER_BRIDGE
            @under_bridge_passages[[x, y]] = -1
          end
          if @under_bridge_passages[[x, y]] != 0 and Data_Tile::BRIDGE_BREADTH.include?(tile_id[2])
            @keep_back_position.push([x, round_y(y+1)])
          end
        elsif tile_id[2] != 0 and @passages[tile_id[2]] & 0x10 == 0x10
          if @back_tiles_position.include?([x, round_y(y+1)])
            @keep_back_position.push([x, y])
          else
            @ex_data[x, y, 2] = @map.data[x, y, 2]
          end
        end
        if (2816...8192).include?(tile_id[0])
          if back_tiles.include?(tile_id[0])
            @back_tiles_position.push([x, y])
            @ex_data[x, y, 0] = @map.data[x, y, 0]
            @ex_data[x, y, 1] = @map.data[x, y, 1]
            if tile_id[2] != Expansion_Passable::ADDITION_BACK_TILE_ID
              @ex_data[x, y, 2] = @map.data[x, y, 2]
            end
            @map.data[x, y, 1] = 0
            @map.data[x, y, 2] = 0
            if Expansion_Passable::BACK_TILE_DEEP
              unless @back_tiles_position.include?([x, round_y(y+1)])
                unless wall?(data[x, round_y(y+1), 0]) and 
                       verge?(data[x, round_y(y+1), 0], 2)
                  @back_tiles_position.push([x, round_y(y+1)])
                  @ex_data[x, round_y(y+1), 0] = @map.data[x, round_y(y+1), 0]
                  @ex_data[x, round_y(y+1), 1] = @map.data[x, round_y(y+1), 1]
                  @ex_data[x, round_y(y+1), 2] = @map.data[x, round_y(y+1), 2]
                  @map.data[x, round_y(y+1), 1] = 0
                  @map.data[x, round_y(y+1), 2] = 0
                end
              end
            end
          elsif Expansion_Passable::ADDITION_BACK_TILE_ID != nil and
                tile_id[2] == Expansion_Passable::ADDITION_BACK_TILE_ID
            @back_tiles_position.push([x, y])
            @ex_data[x, y, 0] = @map.data[x, y, 0]
            @ex_data[x, y, 1] = @map.data[x, y, 1]
            @map.data[x, y, 1] = 0
            @map.data[x, y, 2] = 0
            if (2816...8192).include?(@map.data[x, round_y(y-1), 0])
              @ex_data[x, round_y(y-1), 0] = @map.data[x, round_y(y-1), 0]
              @ex_data[x, round_y(y-1), 1] = @map.data[x, round_y(y-1), 1]
            end
          end
        end
      end
    end
    
    if Expansion_Passable::DELETE_BACK_TILE_ID != nil
      for x in 0...width
        for y in 0...height
          if @ex_data[x, y, 2] == Expansion_Passable::DELETE_BACK_TILE_ID
            @back_tiles_position.delete([x, y])
            @ex_data[x, y, 2] = 0
          elsif @map.data[x, y, 2] == Expansion_Passable::DELETE_BACK_TILE_ID
            @map.data[x, y, 2] = 0
          end
        end
      end
    end
    
  end
  #--------------------------------------------------------------------------
  # ○ 裏回り用タイルの存在する座標か？
  #--------------------------------------------------------------------------
  def back_tile?(x, y)
    return false if @back_tiles_position == nil
    return @back_tiles_position.include?([x, y])
  end
end

#==============================================================================
# ■ Game_Character
#------------------------------------------------------------------------------
# 　キャラクターを扱うクラスです。このクラスは Game_Player クラスと Game_Event
# クラスのスーパークラスとして使用されます。
#==============================================================================

class Game_Character
  #--------------------------------------------------------------------------
  # ○ 公開インスタンス変数
  #--------------------------------------------------------------------------
  attr_reader   :on_tile
  attr_reader   :turn_back
  attr_accessor :no_turn_back
  attr_reader   :not_back_seeing
  #--------------------------------------------------------------------------
  # ◎ オブジェクト初期化
  #--------------------------------------------------------------------------
  alias tig_ep_initialize initialize
  def initialize
    tig_ep_initialize
    @vehicle_type = -1
    @turn_back = false
    @no_turn_back = false
    @on_tile = true
    @back_seeing = false
    @not_back_seeing = false
  end
  #--------------------------------------------------------------------------
  # ◎ フレーム更新
  #--------------------------------------------------------------------------
  alias tig_ep_update update
  def update
    if @first_update == nil
      update_turn_back
      @first_update = true
    end
    tig_ep_update
  end
  #--------------------------------------------------------------------------
  # ◎ 茂み深さの更新
  #--------------------------------------------------------------------------
  alias tig_ep_update_bush_depth update_bush_depth
  def update_bush_depth
    update_turn_back
    tig_ep_update_bush_depth
  end
  #--------------------------------------------------------------------------
  # ○ 裏回り状態更新
  #--------------------------------------------------------------------------
  def update_turn_back
    unless @real_x == @x * 256 and @real_y == @y * 256
      @back_seeing = false
      @on_tile = false if @turn_back
    else
      @turn_back = false if @no_turn_back
      unless $game_map.back_tile?(@x, @y)
        @turn_back = false
        @no_turn_back = false
      end
      @on_tile = true unless @turn_back
    end
    if not @turn_back or @no_turn_back
      if $game_map.keep_back_position != nil and $game_map.keep_back_position.include?([@x, @y])
        @on_tile = false
        return
      end
    end
  end
  #--------------------------------------------------------------------------
  # ○ 段差マップ用・拡張通過判定
  #--------------------------------------------------------------------------
  def ex_passable(direction, test = false) 
    front_x = $game_map.x_with_direction(@x, direction)
    front_y = $game_map.y_with_direction(@y, direction)    
    tile_id = $game_map.point_tile_id(@x, @y)
    front_tile_id = $game_map.point_tile_id(front_x, front_y)
    
    if Data_Tile::STEP.include?(front_tile_id[0]) or
       Data_Tile::STEP.include?(front_tile_id[2])
      return true
    else
      unless $game_map.wall?(front_tile_id[0])
        return true if Data_Tile::STEP.include?(tile_id[0])
        return true if Data_Tile::STEP.include?(tile_id[2])
      end
    end
    
    if $game_map.back_tiles_position.include?([@x, @y]) and @turn_back # この場が裏
      if $game_map.under_bridge_passages.key?([front_x, front_y])
        if (@vehicle_type == -1 and $game_map.under_bridge_passages[[front_x, front_y]] == 1) or
           $game_map.under_bridge_passages[[front_x, front_y]] <= 0
          return false unless debug_through? or @through
        end
      end
      if $game_map.back_tiles_position.include?([front_x, front_y]) # 目の前が裏
        return true
      else                                                 # 目の前が裏でない
        if $game_map.rip?(tile_id, front_tile_id, direction)        # この場に境目がある
          if $game_map.rip?(front_tile_id, tile_id, 10 - direction) # 目の前に境目がある
            return false unless debug_through? or @through # 通行不可
          else
            return true
          end
        else                                               # この場に境目がない 
          return false unless debug_through? or @through   # 通行不可
        end
      end
    else                                                   # この場は裏でない
      unless $game_map.bridge?(front_tile_id[2], direction) or # 橋がなければ
             $game_map.bridge?(tile_id[2], direction)    
        if $game_map.rip?(tile_id, front_tile_id, direction) # この場に境目がある
          return false unless debug_through? or @through # 通行不可
        else                                               # この場に境目がない
          if $game_map.rip?(front_tile_id, tile_id, 10 - direction) # 目の前に境目がある
            if $game_map.back_tiles_position.include?([front_x, front_y]) # 目の前が裏タイル
              unless $game_map.bridge?(tile_id[2], direction)   # この場が橋でなければ
                if $game_map.under_bridge_passages.key?([front_x, front_y])
                  if (@vehicle_type == -1 and $game_map.under_bridge_passages[[front_x, front_y]] == 1) or
                     $game_map.under_bridge_passages[[front_x, front_y]] <= 0
                    return false unless debug_through? or @through
                  end
                end
                unless @no_turn_back
                  @turn_back = true unless test            # 裏回り開始
                  @back_seeing = true
                end
              end
            else                                           # 目の前が裏タイルでない
              unless $game_map.bridge?(tile_id[2], direction) # この場が橋でなければ
                return false unless debug_through? or @through # 通行不可
              end
            end
          else                                             # 目の前に境目がない
            if $game_map.wall?(front_tile_id[0])
              return false unless debug_through? or @through # 通行不可
            end
          end
        end
      end
    end
    
    if $game_map.back_tile?(front_x, front_y) and not @turn_back 
      for i in [2, 1, 0]                        # レイヤーの上から順に調べる
        tile_id = $game_map.ex_data[front_x, front_y, i] # タイル ID を取得
        unless tile_id == nil
          pass = $game_map.passages[tile_id]    # 通行属性を取得
          next if pass & 0x10 == 0x10           # [☆] : 通行に影響しない
          next if pass & 0x01 == 0x00           # [○] : 通行可
          if pass & 0x01 == 0x01                # [×] : 通行不可
            return false unless debug_through? or @through
          end
        end
      end
    end  

    return true
  end
  #--------------------------------------------------------------------------
  # ◎ 下に移動
  #     turn_ok : その場での向き変更を許可
  #--------------------------------------------------------------------------
  alias tig_ep_move_down move_down
  def move_down(turn_ok = true)
    last_turn_back = @turn_back
    unless ex_passable(2)
      turn_down if turn_ok
      @move_failed = true
      check_event_trigger_touch(@x, @y+1)   # 接触イベントの起動判定
      return
    end
    tig_ep_move_down(turn_ok)
    if @move_failed and @turn_back and not last_turn_back
      @turn_back = false
    end
  end
  #--------------------------------------------------------------------------
  # ◎ 左に移動
  #     turn_ok : その場での向き変更を許可
  #--------------------------------------------------------------------------
  alias tig_ep_move_left move_left 
  def move_left(turn_ok = true)
    last_turn_back = @turn_back
    unless ex_passable(4)
      turn_left if turn_ok
      @move_failed = true
      check_event_trigger_touch(@x-1, @y)   # 接触イベントの起動判定
      return
    end
    tig_ep_move_left(turn_ok)
    if @move_failed and @turn_back and not last_turn_back
      @turn_back = false
    end
  end
  #--------------------------------------------------------------------------
  # ◎ 右に移動
  #     turn_ok : その場での向き変更を許可
  #--------------------------------------------------------------------------
  alias tig_ep_move_right move_right
  def move_right(turn_ok = true)
    last_turn_back = @turn_back
    unless ex_passable(6)
      turn_right if turn_ok
      check_event_trigger_touch(@x+1, @y)   # 接触イベントの起動判定
      @move_failed = true
      return
    end
    tig_ep_move_right(turn_ok)
    if @move_failed and @turn_back and not last_turn_back
      @turn_back = false
    end
  end
  #--------------------------------------------------------------------------
  # ◎ 上に移動
  #     turn_ok : その場での向き変更を許可
  #--------------------------------------------------------------------------
  alias tig_ep_move_up move_up
  def move_up(turn_ok = true)
    last_turn_back = @turn_back
    unless ex_passable(8)
      turn_up if turn_ok
      check_event_trigger_touch(@x, @y-1)   # 接触イベントの起動判定
      @move_failed = true
      return
    end
    tig_ep_move_up(turn_ok)
    if @move_failed and @turn_back and not last_turn_back
      @turn_back = false
    end
  end
  #--------------------------------------------------------------------------
  # ● キャラクター衝突判定
  #     x : X 座標
  #     y : Y 座標
  #    プレイヤーと乗り物を含め、通常キャラの衝突を検出する。
  #--------------------------------------------------------------------------
  def collide_with_characters?(x, y)
    for event in $game_map.events_xy(x, y)          # イベントの座標と一致
      next unless parallel?(event)                  ##### 追加部分 (この行) #####
      unless event.through                          # すり抜け OFF？
        return true if self.is_a?(Game_Event)       # 自分がイベント
        return true if event.priority_type == 1     # 相手が通常キャラ
      end
    end
    if @priority_type == 1                          # 自分が通常キャラ
      return true if $game_player.pos_nt?(x, y)     # プレイヤーの座標と一致
      return true if $game_map.boat.pos_nt?(x, y)   # 小型船の座標と一致
      return true if $game_map.ship.pos_nt?(x, y)   # 大型船の座標と一致
    end
    return false
  end
  #--------------------------------------------------------------------------
  # ○ キャラクターの同軸存在判定
  #--------------------------------------------------------------------------
  def parallel?(event)
    
    if @x == event.x
      if @y < event.y
        direction = 2
      elsif @y > event.y
        direction = 8
      end
    elsif  @y = event.y
      if @x < event.x
        direction = 6
      elsif @x > event.x
        direction = 4
      end
    end
    
    return @turn_back == event.turn_back if direction == nil
    last_turn_back = @turn_back
    passable = ex_passable(direction)
    tile_id = $game_map.data[event.x, event.y, 0]
    unless $game_map.wall?(tile_id)
      return false unless passable
    end
    
    if last_turn_back != @turn_back
      @turn_back = last_turn_back
      return @turn_back != event.turn_back
    else
      return true unless $game_map.back_tile?(event.x, event.y)
      return @turn_back == event.turn_back
    end
    
  end
end

#==============================================================================
# ■ Game_Event
#------------------------------------------------------------------------------
# 　イベントを扱うクラスです。条件判定によるイベントページ切り替えや、並列処理
# イベント実行などの機能を持っており、Game_Map クラスの内部で使用されます。
#==============================================================================

class Game_Event < Game_Character
  #--------------------------------------------------------------------------
  # ◎ オブジェクト初期化
  #     map_id : マップ ID
  #     event  : イベント (RPG::Event)
  #--------------------------------------------------------------------------
  alias tig_ep_event_initialize initialize
  def initialize(map_id, event)
    tig_ep_event_initialize(map_id, event)
    set_turn_back_setting
  end
  #--------------------------------------------------------------------------
  # ○ Get Initial Arrangement Position (Place behind)
  #--------------------------------------------------------------------------  
  def set_turn_back_setting
    @event.name = @event.name.sub(/[\<＜]behind[\>＞]/, "") 
    @turn_back = $& != nil
    @on_tile = $& == nil
    @event.name = @event.name.sub(/[\<＜]hidebehind[\>＞]/, "") 
    @not_back_seeing = $& != nil
  end
end

#==============================================================================
# ** Game_Vehicle
#------------------------------------------------------------------------------
# 　乗り物を扱うクラスです。このクラスは Game_Map クラスの内部で使用されます。
# 現在のマップに乗り物がないときは、マップ座標 (-1,-1) に設定されます。
#==============================================================================

class Game_Vehicle < Game_Character  
  def on_tile
    if @driving
      return $game_player.on_tile
    else
      return @on_tile
    end
  end
end

#==============================================================================
# ** Game_Player
#------------------------------------------------------------------------------
# 　プレイヤーを扱うクラスです。イベントの起動判定や、マップのスクロールなどの
# 機能を持っています。このクラスのインスタンスは $game_player で参照されます。
#==============================================================================

class Game_Player < Game_Character
  #--------------------------------------------------------------------------
  # ○ 裏配置イベント透過状態か？
  #--------------------------------------------------------------------------   
  def back_seeing?
    return true if @turn_back or @back_seeing
    return false
  end
  #--------------------------------------------------------------------------
  # ● 同位置のイベント起動判定
  #     triggers : トリガーの配列
  #--------------------------------------------------------------------------
  def check_event_trigger_here(triggers)
    return false if $game_map.interpreter.running?
    result = false
    for event in $game_map.events_xy(@x, @y)
      next unless parallel?(event)                 ##### 追加部分 (この行) #####
      if triggers.include?(event.trigger) and event.priority_type != 1
        event.start
        result = true if event.starting
      end
    end
    return result
  end
  #--------------------------------------------------------------------------
  # ● 正面のイベント起動判定
  #     triggers : トリガーの配列
  #--------------------------------------------------------------------------
  def check_event_trigger_there(triggers)
    return false if $game_map.interpreter.running?
    result = false
    front_x = $game_map.x_with_direction(@x, @direction)
    front_y = $game_map.y_with_direction(@y, @direction)
    for event in $game_map.events_xy(front_x, front_y)
      next unless parallel?(event)                 ##### 追加部分 (この行) #####
      if triggers.include?(event.trigger) and event.priority_type == 1
        event.start
        result = true
      end
    end
    if result == false and $game_map.counter?(front_x, front_y)
      front_x = $game_map.x_with_direction(front_x, @direction)
      front_y = $game_map.y_with_direction(front_y, @direction)
      for event in $game_map.events_xy(front_x, front_y)
        next unless parallel?(event)               ##### 追加部分 (この行) #####
        if triggers.include?(event.trigger) and event.priority_type == 1
          event.start
          result = true
        end
      end
    end
    return result
  end
  #--------------------------------------------------------------------------
  # ◎ 乗り物から降りる
  #    現在乗り物に乗っていることが前提。
  #--------------------------------------------------------------------------
  alias tig_ep_get_off_vehicle get_off_vehicle
  def get_off_vehicle
    return if $game_map.back_tile?(@x, @y)
    if @vehicle_type == 0 or @vehicle_type == 1
      front_x = $game_map.x_with_direction(@x, @direction)
      front_y = $game_map.y_with_direction(@y, @direction)
      return if $game_map.under_bridge_passages[[front_x, front_y]] == 1
      return if $game_map.prohibited_get_off.include?([front_x, front_y])
      @no_turn_back = true 
    end
    tig_ep_get_off_vehicle
  end
end

#==============================================================================
# ** Spriteset_Map
#------------------------------------------------------------------------------
# 　マップ画面のスプライトやタイルマップなどをまとめたクラスです。このクラスは
# Scene_Map クラスの内部で使用されます。
#==============================================================================

class Spriteset_Map
  #--------------------------------------------------------------------------
  # ◎ ビューポートの作成
  #--------------------------------------------------------------------------
  alias tig_ep_create_viewports create_viewports
 def create_viewports
    tig_ep_create_viewports
    @viewport4 = Viewport.new(0, 0, 640, 480) # 追加レイヤー�"��"ューポート
    if Expansion_Passable::BACK_SEEING
      @viewport5 = Viewport.new(0, 0, 640, 480) # 裏回りキャラ透過�"��"ューポート
    end
    @viewport6 = Viewport.new(0, 0, 640, 480) # 色調変更�"��"ューポート
  end
  #--------------------------------------------------------------------------
  # ◎ タイルマップの作成
  #--------------------------------------------------------------------------
  alias tig_ep_create_tilemap create_tilemap
  def create_tilemap
    tig_ep_create_tilemap
    setup_shadow_eraser_tilemap
    @ex_tilemap = Tilemap.new(@viewport4)
    @ex_tilemap.bitmaps[0] = Cache.system("TileA1")
    @ex_tilemap.bitmaps[1] = Cache.system("TileA2")
    @ex_tilemap.bitmaps[2] = Cache.system("TileA3")
    @ex_tilemap.bitmaps[3] = Cache.system("TileA4")
    @ex_tilemap.bitmaps[4] = Cache.system("TileA5")
    @ex_tilemap.bitmaps[5] = Cache.system("TileB")
    @ex_tilemap.bitmaps[6] = Cache.system("TileC")
    @ex_tilemap.bitmaps[7] = Cache.system("TileD")
    @ex_tilemap.bitmaps[8] = Cache.system("TileE")
    @ex_tilemap.map_data = $game_map.ex_data
    @ex_tilemap.passages = $game_map.passages
  end
  #--------------------------------------------------------------------------
  # ○ 影消し処理用タイルの準備
  #--------------------------------------------------------------------------
  def setup_shadow_eraser_tilemap
    for i in 1952...2048
      @tilemap.passages[i] = 0x00
    end
  end 
  #--------------------------------------------------------------------------
  # ◎ 飛行船の影スプライトの作成
  #--------------------------------------------------------------------------
  alias tig_ep_create_shadow create_shadow
  def create_shadow
    tig_ep_create_shadow
    @shadow_sprite.viewport = @viewport4
  end
  #--------------------------------------------------------------------------
  # ◎ タイルマップの解放
  #--------------------------------------------------------------------------
  alias tig_ep_dispose_tilemap dispose_tilemap
  def dispose_tilemap
    tig_ep_dispose_tilemap
    @ex_tilemap.dispose
  end
  #--------------------------------------------------------------------------
  # ◎ ビューポートの解放
  #--------------------------------------------------------------------------
  alias tig_ep_dispose_viewports dispose_viewports
  def dispose_viewports
    tig_ep_dispose_viewports
    @viewport4.dispose
    @viewport5.dispose if Expansion_Passable::BACK_SEEING
    @viewport6.dispose
  end
  #--------------------------------------------------------------------------
  # ◎ タイルマップの更新
  #--------------------------------------------------------------------------
  alias tig_ep_update_tilemap update_tilemap
  def update_tilemap
    tig_ep_update_tilemap
    @ex_tilemap.ox = $game_map.display_x / 8
    @ex_tilemap.oy = $game_map.display_y / 8
    @ex_tilemap.update
  end
  #--------------------------------------------------------------------------
  # ◎ キャラクタースプライトの更新
  #--------------------------------------------------------------------------
  alias tig_ep_update_characters update_characters
  def update_characters
    back_seeing_characters = []
    for sprite in @character_sprites
      next if sprite.character.not_back_seeing
      if $game_player.back_seeing? and Expansion_Passable::BACK_SEEING
        x = $game_player.x ; y = $game_player.y
        if ($game_map.round_x(x-2)..$game_map.round_x(x+2)).include?(sprite.character.x) and
           ($game_map.round_y(y-2)..$game_map.round_y(y+2)).include?(sprite.character.y)
          back_seeing_characters.push(sprite.character)
        end
      end
      if sprite.character.on_tile
        sprite.viewport = @viewport4
      else
        sprite.viewport = @viewport1
      end
    end
    back_seeing(back_seeing_characters)
    
    tig_ep_update_characters 
  end
  #--------------------------------------------------------------------------
  # ○ 裏回りキャラ透過
  #--------------------------------------------------------------------------  
  def back_seeing(characters)
    return unless Expansion_Passable::BACK_SEEING
    @back_seeing_sprites = [] if @back_seeing_sprites == nil
    @characters = [] if @characters == nil
    now_character = []
    for character in characters
      now_character.push(character)
      unless @characters.include?(character)
        new_sprite = Sprite_Character.new(@viewport5, character)
        new_sprite.back_seeing = true
        @back_seeing_sprites.push(new_sprite)
        @characters.push(new_sprite.character)
      end
    end
    
    for sprite in @back_seeing_sprites
      if now_character.include?(sprite.character)
        sprite.update
      else
        @characters.delete(sprite.character)
        sprite.dispose
        @back_seeing_sprites.delete(sprite)
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● ビューポートの更新
  #--------------------------------------------------------------------------
  def update_viewports
    @viewport6.tone = $game_map.screen.tone        ##### 修正部分 (この行) #####
    @viewport1.ox = $game_map.screen.shake
    
    @viewport4.ox = $game_map.screen.shake         ### 追加部分 (この行から) ###
    if Expansion_Passable::BACK_SEEING
      @viewport5.rect.set($game_player.screen_x - 48, $game_player.screen_y - 64, 96, 96) 
      @viewport5.ox = $game_map.screen.shake
    end                                            ### 追加部分 (ここ行まで) ###
    
    @viewport2.color = $game_map.screen.flash_color
    @viewport3.color.set(0, 0, 0, 255 - $game_map.screen.brightness)
    @viewport1.update
    @viewport2.update
    @viewport3.update
    
    @viewport4.update                              ### 追加部分 (この行から) ###
    @viewport5.update if Expansion_Passable::BACK_SEEING
    @viewport6.update                              ### 追加部分 (ここ行まで) ###
  end
end

#==============================================================================
# ** Sprite_Character
#------------------------------------------------------------------------------
# 　キャラクター表示用のスプライトです。Game_Character クラスのインスタンスを
# 監視し、スプライトの状態を自動的に変化させます。
#==============================================================================

class Sprite_Character < Sprite_Base
  #--------------------------------------------------------------------------
  # ○ 公開インスタンス変数
  #--------------------------------------------------------------------------
  attr_accessor :back_seeing
  #--------------------------------------------------------------------------
  # ◎ オブジェクト初期化
  #     viewport  : ビューポート
  #     character : キャラクター (Game_Character)
  #--------------------------------------------------------------------------
  alias tig_ep_initialize initialize
  def initialize(viewport, character = nil)
    tig_ep_initialize(viewport, character)
    @back_seeing = false
  end
  #--------------------------------------------------------------------------
  # ◎ フレーム更新
  #--------------------------------------------------------------------------
  alias tig_ep_update update
  def update
    tig_ep_update
    if @back_seeing
      self.opacity = 40 if self.opacity > 100
      self.x -= $game_player.screen_x - 48
      self.y -= $game_player.screen_y - 64
    end
  end
end

#==============================================================================
# ** Scene_Title
#------------------------------------------------------------------------------
# 　タイトル画面の処理を行うクラスです。
#==============================================================================

class Scene_Title < Scene_Base
  #--------------------------------------------------------------------------
  # ◎ データベースのロード
  #    name から<船の橋下通過>の設定を得ます。
  #--------------------------------------------------------------------------
  alias tig_ep_load_database load_database
  def load_database
    tig_ep_load_database
    for area in $data_areas.values
      area.name = area.name.sub(/[\<＜]bridge[\>＞]/, "") # adjust area name
      area.ship_pass = $& != nil                         # set ship passability
    end
  end
end